﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


namespace ALE.TesteOfType
{
    /// <summary>
    /// Tutorial de LINQ, com diferente ejemplos.
    /// </summary>
    class Program
    {
        static object[] objetos = { "LINQ", 1, 23.4f, "Perro", new object(), "Casa"};

        static void Main(string[] args)
        {
            //Ejemplo de OfType<TypeResult>
            IEnumerable<string> cadenas = objetos.OfType<string>();
            foreach (string palabra in cadenas) Console.Write(palabra + ", ");

            #region Ejemplo Where

            //Ejemplo de Where
            var libros = new List<String>{
                "Programando en C#",
                "Programando en Java",
                "LINQ iniciantes",
                "Empezando con LINQ",
                "LINQ Avanzado"
            };
            IEnumerable<string> librosLINQ = from libro in libros
                                             where libro.Contains("LINQ")
                                             select libro;

            foreach (string libro in librosLINQ) Console.Write("\n" + libro + ", ");

            //Ejemplo de Where con índice
            IEnumerable<string> librosLINQ2 = libros.Where((libro, index) =>
                                                            libro.Contains("LINQ") && index < 3);
            foreach (string libro in librosLINQ2) Console.Write("\n" + libro + ", ");

            #endregion

            #region Ejemplo Select

            //Ejemplo de Select
            List<Persona> personas =
                new List<Persona>
                {
                    new Persona("Alejandro",
                                24,
                                new List<string>{"Ipod", "HTC Diamond"}
                                ),
                    new Persona("Juan",
                                33,
                                new List<string>{"vaio", "Adroid"}
                                ),
                    new Persona("Alvaro",
                                22,
                                new List<string>{"Pentium", "Movil ladrillo"}
                                )
                };

            //i) Select standard...
            Console.WriteLine("Nombres");
            IEnumerable<string> nombres = personas.Select(persona => persona.Nombre);
            foreach (string nombre in nombres) Console.Write("\n" + nombre + ", ");
            //ii) Select con query expresion...
            Console.WriteLine("Nombres");
            IEnumerable<string> nombres2 = from persona in personas
                                           select persona.Nombre;
            foreach (string nombre in nombres) Console.Write("\n" + nombre + ", ");
            //iii) Select utilizando tipos anónimos.
            var nombreYEdad = from persona in personas
                              select new { persona.Nombre, persona.Edad };
            Console.WriteLine("Gadgets");
            IEnumerable<List<string>> listaGadgets2 = from persona in personas
                                          select persona.Gadgets;
            foreach (var gadgets in listaGadgets2)
                foreach (var gadget in gadgets)
                    Console.Write("\n" + gadget + ", ");
            //iv) Utilizando SelectMany
            IEnumerable<string> listaGadgets3 = personas.SelectMany(persona => persona.Gadgets);
            foreach (string gadget in listaGadgets3) Console.Write("\n" + gadget + ", ");
            Console.WriteLine("Nuevamente Gadgets ");
            IEnumerable<string> listaGadgets4 = from persona in personas
                                                from gadget in persona.Gadgets
                                                select gadget;
            foreach (string gadget in listaGadgets4) Console.Write("\n" + gadget + ", ");
            //v) Utilizando SelctMany + Función + Índice
            IEnumerable<string> listaGadgets5 = personas.SelectMany((persona, indice) =>
                                            persona.Gadgets.Select(gadget => indice + " - " + gadget), (persona, gadget) => gadget.ToUpper());
            foreach (string gadget in listaGadgets5) Console.Write("\n" + gadget + ", ");

            #endregion

            #region Ejemplo Partitioning

            List<string> listaNombres = new List<string>
            {
                "ale",
                "jandro",
                "raul",
                "daniel",
                "lita",
                "mariela",
                "melina"
            };

            //i) Uso de Skip.
            IEnumerable<string> lista = listaNombres.Skip(3);
            foreach (string nombre in lista) Console.Write("\n" + nombre + ", ");
            //ii) Uso de SkipWhile
            List<double> listaNotas = new List<double>
            {
                0, 1, 2, 3, 4, 5, 6, 7, 7.6,  8, 9, 10
            };

            IEnumerable<double> notas = listaNotas.SkipWhile(nota => nota < 5);
            foreach (double nota in notas) Console.Write("\n" + nota + ", ");
            //iii) Uso de Take
            IEnumerable<double> notas2 = listaNotas.Take(5);
            foreach (double nota in notas2) Console.Write("\n" + nota + ", ");
            //iii) Uso de TakeWhile
            IEnumerable<double> notas3 = listaNotas.TakeWhile(nota => nota < 5);
            foreach (double nota in notas3) Console.Write("\n" + nota + ", ");

            #endregion

            #region Ejemplo de Join

            Provincia buenosAires = new Provincia("Buenos Aires");
            Provincia entreRios = new Provincia("Entre Rios");
            Provincia chubut = new Provincia("Chubut");
            Provincia tierraDelFuego = new Provincia("Tierra del Fuego");

            Ciudad ciudadBsAs = new Ciudad("Ciudad de Buenos Aires", buenosAires);
            Ciudad moron = new Ciudad("Moron", buenosAires);
            Ciudad quilmes = new Ciudad("Quilmes", buenosAires);
            Ciudad parana = new Ciudad("Parana", entreRios);
            Ciudad esquel = new Ciudad("Esquel", chubut);
            Ciudad ushuaia = new Ciudad("Ushuaia", tierraDelFuego);

            List<Provincia> listaProvincias = new List<Provincia> { buenosAires, entreRios, chubut, tierraDelFuego };
            List<Ciudad> listaCiudades = new List<Ciudad> { ciudadBsAs, moron, quilmes, parana, esquel, ushuaia };

            var query = listaProvincias.GroupJoin(listaCiudades,
                                                provincia => provincia,
                                                ciudades => ciudades.Localizacion,
                                                (provincia, ciudades) => new { provincia, ciudades });


            #endregion
        }
    }

    /// <summary>
    /// Clase auxiliar para los ejemplos.
    /// </summary>
    class Persona
    {
        public string Nombre { get; set; }
        public int Edad { get; set; }
        public List<string> Gadgets { set; get; }

        public Persona(string nombre, int edad, List<string> gadgets)
        {
            Nombre = nombre;
            Edad = edad;
            Gadgets = gadgets;
        }
    }

    class Provincia
    {
        public string Nombre { get; set; }

        public Provincia(string nombre)
        {
            Nombre = nombre;
        }
    }

    class Ciudad
    {
        public string Nombre { get; set; }
        public Provincia Localizacion { set; get; }

        public Ciudad(string nombre, Provincia localizacion)
        {
            Nombre = nombre;
            Localizacion = localizacion;
        }
   }
}
